package com.toy.core.config;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSONObject;
import com.google.common.base.Optional;
import com.toy.core.security.login.entrypoint.LoginEntryPoint;
import com.toy.core.security.logout.handler.LogoutHandler;
import com.toy.core.security.userdetails.UserDetailsService;

@Component("sysConfig")
public class SysConfigImpl implements SysConfig,InitializingBean ,ApplicationContextAware{
	/**
	 * Logger for this class
	 */
	private static final Logger logger = Logger.getLogger(SysConfigImpl.class);
	
	public final static String CONFIG = "classpath:/config/toy_config.properties";
	
	private Properties properties;
	
	private ApplicationContext applicationContext;
	
	public void afterPropertiesSet() throws Exception {
		Executors.newScheduledThreadPool(1).scheduleWithFixedDelay(
				new PropertiesTask(), 2, 60, TimeUnit.SECONDS);
	}
	
	public String getOption(String key){
		return Optional.of(properties.getProperty(key)).get();
	}
	
	public String getHomePageUrl(){
		return getOption(SECURITY_SYSTEM_HOMEPAGE_URL);
	}
	
	public String getLogoutUrl(){
		return getOption(SECURITY_SYSTEM_LOGOUT_URLMARK);
	}
	
	public String getAccessDeniedPageUrl(){
		return getOption(SECURITY_SYSTEM_ACCESSDENIEDPAGE_URL);
	}
	
	public List<String> getPublicUrls(){
		String publicUrl = getOption(SECURITY_SYSTEM_URL_PUBLIC);
		String[] arrayUrls = StringUtils.split(publicUrl, ",");
		return Arrays.asList(arrayUrls);
	}
	
	public LoginEntryPoint getLoginEntryPoint(){
		String loginType = getOption(SECURITY_SSO_LOGIN_TYPE);
		String mapping = getOption(SECURITY_SSO_LOGIN_MAPPING);
		JSONObject mappingJSON = JSONObject.parseObject(mapping);
		String entryPointBeanName = (String)mappingJSON.get(loginType);
		entryPointBeanName = Optional.of(entryPointBeanName).get();
		return applicationContext.getBean(entryPointBeanName,LoginEntryPoint.class);
	}
	
	public String getCookieName(){
		return getOption(SECURITY_SSO_COOKIE_NAME);
	}
	
	public String getTicketRequestParam(){
		return getOption(SECURITY_SSO_TICKET_REQUEST_PARAM);
	}
	
	public LogoutHandler[] getLogoutChain(){
		String logoutChain = getOption(SECURITY_SSO_CHAIN_LOGOUT_HANDLER);
		String[] handlerArray = StringUtils.split(logoutChain, ",");
		List<LogoutHandler> handlers = new ArrayList<LogoutHandler>();
		for (String handlerName : handlerArray) {
			LogoutHandler logoutHandler = applicationContext.getBean(handlerName,LogoutHandler.class);
			logoutHandler = Optional.of(logoutHandler).get();
			handlers.add(logoutHandler);
		}
		return handlers.toArray(new LogoutHandler[handlers.size()]);
	}
	
	public String getStorageLoginInputUrl(){
		return getOption(SECURITY_SSO_STORAGE_LOGIN_INPUT_URL);
	}
	
	public String getStorageLoginValidateUrl(){
		return getOption(SECURITY_SSO_STORAGE_LOGIN_VALIDATE_URL);
	}
	
	public UserDetailsService getStorageUserDetailsService(){
		String beanName = getOption(SECURITY_SSO_STORAGE_AUTHENTICATION_BEAN_NAME);
		return applicationContext.getBean(beanName, UserDetailsService.class);
	}
	
	public String getCasLoginUrl(){
		return getOption(SECURITY_SSO_CAS_LOGIN_URL);
	}
	
	public String getCasValidateUrl() {
		return getOption(SECURITY_SSO_CAS_VALIDATE_URL);
	}
	
	public String getCasLoginValidateUrl(){
		return getOption(SECURITY_SSO_CAS_LOGIN_VALIDATE_URL);
	}
	
	public String getNtlmConfig(){
		return getOption(SECURITY_SSO_NTLM_CONFIG);
	}
	
	public String getNtmlLoginValidateUrl(){
		return getOption(SECURITY_SSO_NTLM_LOGIN_VALIDATE_URL);
	}
	
	class PropertiesTask extends Thread {
		private long lastModified = 0;
		@Override
		public void run() {
			try {
				Resource resource = new DefaultResourceLoader().getResource(CONFIG);
				File file = resource.getFile();
				long lastUpdateTime = file.lastModified();
				if ( lastUpdateTime > lastModified ){
					if (logger.isDebugEnabled()) {logger.debug("The config properties file was modified."); }
					properties = new Properties();
					properties.load(new ByteArrayInputStream(FileUtils.readFileToByteArray(file)));
					lastModified = lastUpdateTime;
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
			
		}
	}

	public void setApplicationContext(ApplicationContext applicationContext)
			throws BeansException {
		this.applicationContext = applicationContext;
	}

}
